﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace yiwei.Repository.back
{

    public interface IRepository<T> where T : class
    {
        #region Find --query

        #region Sync
        /// <summary>
        /// 根据条件查询单个实体
        /// </summary>
        /// <param name="exp">条件</param>
        /// <returns>返回实体</returns>
        T FindSingle(Expression<Func<T, bool>> exp = null);
        /// <summary>
        /// 根据条件判断是否 有数据
        /// </summary>
        /// <param name="exp">条件</param>
        /// <returns></returns>
        bool IsExist(Expression<Func<T, bool>> exp);

        /// <summary>
        /// 根据条件查询数据
        /// </summary>
        /// <param name="exp">条件</param>
        /// <returns>返回查询结果集</returns>
        IQueryable<T> Find(Expression<Func<T, bool>> exp = null);

        /// <summary>
        /// 根据条件分页查询
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="predicate">条件</param>
        /// <param name="orderField">排序</param>
        /// <param name="pageSize">每页数量</param>
        /// <param name="pageIndex">当前页码</param>
        /// <param name="orderTypes">排序类型，默认正序排序</param>
        /// <returns>返回集合和总记录数</returns>
        (IEnumerable<T> list, long total) Find(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderField, int pageSize, int pageIndex, params OrderType[] orderTypes);

        /// <summary>
        /// 获取满足条件的数量
        /// </summary>
        /// <param name="exp">条件</param>
        /// <returns>数量</returns>
        int GetCount(Expression<Func<T, bool>> exp = null);
        #endregion

        #region ASync

        /// <summary>
        /// 根据条件查询单个实体
        /// </summary>
        /// <param name="exp">条件</param>
        /// <returns>返回实体</returns>
        Task<T> FindSingleASync(Expression<Func<T, bool>> exp = null);
        /// <summary>
        /// 根据条件判断是否 有数据
        /// </summary>
        /// <param name="exp">条件</param>
        /// <returns></returns>
        Task<bool> IsExistASync(Expression<Func<T, bool>> exp);

        /// <summary>
        /// 根据条件查询数据
        /// </summary>
        /// <param name="exp">条件</param>
        /// <returns>返回查询结果集</returns>
        Task<IQueryable<T>> FindASync(Expression<Func<T, bool>> exp = null);
        /// <summary>
        /// 根据条件分页查询
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="predicate">条件</param>
        /// <param name="orderField">排序</param>
        /// <param name="pageSize">每页数量</param>
        /// <param name="pageIndex">当前页码</param>
        /// <param name="orderTypes">排序类型，默认正序排序</param>
        /// <returns>返回集合和总记录数</returns>
        Task<(IEnumerable<T> list, long total)> FindAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderField, int pageSize, int pageIndex, params OrderType[] orderTypes);

        /// <summary>
        /// 获取满足条件的数量
        /// </summary>
        /// <param name="exp">条件</param>
        /// <returns>数量</returns>
        Task<int> GetCountASync(Expression<Func<T, bool>> exp = null);
        #endregion

        #endregion

        #region Insert-Add

        /// <summary>
        /// 插入单个实体
        /// </summary>
        /// <param name="entity">要插入的实体</param>
        /// <returns>返回受影响行数</returns>
        int Add(T entity);

        /// <summary>
        /// 插入多个实体
        /// </summary>
        /// <param name="entities">要插入的实体集合</param>
        /// <returns>返回受影响行数</returns>
        int Add(IEnumerable<T> entities);

        /// <summary>
        /// 插入单个实体
        /// </summary>
        /// <param name="entity">要插入的实体</param>
        /// <returns>返回受影响行数</returns>
        Task<int> AddAsync(T entity);

        /// <summary>
        /// 插入多个实体
        /// </summary>
        /// <param name="entities">要插入的实体集合</param>
        /// <returns>返回受影响行数</returns>
        Task<int> AddAsync(IEnumerable<T> entities);

        #endregion

        #region Update
        /// <summary>
        /// 更新一个实体的所有属性
        /// </summary>
        int Update(T entity);

        /// <summary>
        /// 实现按需要只更新部分更新
        /// <para>如：Update(u =>u.Id==1,u =>new User{Name="ok"});</para>
        /// </summary>
        /// <param name="where">更新条件</param>
        /// <param name="entity">更新后的实体</param>
        int Update(Expression<Func<T, bool>> where, Expression<Func<T, T>> entity);

        /// <summary>
        /// 更新一个实体的所有属性
        /// </summary>
        Task<int> UpdateAsync(T entity);

        /// <summary>
        /// 实现按需要只更新部分更新
        /// <para>如：Update(u =>u.Id==1,u =>new User{Name="ok"});</para>
        /// </summary>
        /// <param name="where">更新条件</param>
        /// <param name="entity">更新后的实体</param>
        Task<int> UpdateAsync(Expression<Func<T, bool>> where, Expression<Func<T, T>> entity);


        #endregion

        #region Delete

        /// <summary>
        /// 删除单个实体
        /// </summary>
        /// <param name="entity">要删除的实体</param>
        /// <returns>返回受影响行数</returns>
        int Delete(T entity);

        /// <summary>
        /// 按条件删除
        /// </summary>
        int Delete(Expression<Func<T, bool>> exp);

        /// <summary>
        /// 删除多个实体
        /// </summary>
        /// <param name="entities">要删除的实体集合</param>
        /// <returns>返回受影响行数</returns>
        int Delete(IEnumerable<T> entitys);

        /// <summary>
        /// 删除单个实体
        /// </summary>
        /// <param name="entity">要删除的实体</param>
        /// <returns>返回受影响行数</returns>
       Task<int> DeleteAsync(T entity);

        /// <summary>
        /// 按条件删除
        /// </summary>
        Task<int> DeleteAsync(Expression<Func<T, bool>> exp);

        /// <summary>
        /// 删除多个实体
        /// </summary>
        /// <param name="entities">要删除的实体集合</param>
        /// <returns>返回受影响行数</returns>
        Task<int> DeleteAsync(IEnumerable<T> entitys);

        #endregion



        #region Execute-sql

        int ExecuteSql(string sql);
        Task<int> ExecuteSqlAsync(string sql);

        #endregion
    }
    /// <summary>
    /// 排序方式
    /// </summary>
    public enum OrderType
    {
        /// <summary>
        /// 升序
        /// </summary>
        Ascending,

        /// <summary>
        /// 降序
        /// </summary>
        Descending
    }
  
}
